package org.jeecg.report.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.builder.ExcelWriterSheetBuilder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.CommonAPI;
import org.jeecg.report.mapper.ReportMapper;
import org.jeecg.report.service.ReportService;
import org.jeecg.report.util.ReportUtils;
import org.jeecg.report.vo.ColumnVO;
import org.jeecg.report.vo.FTQReportColumnVO;
import org.jeecg.report.vo.FTQReportVO;
import org.jeecg.report.vo.MachineReportVO;

import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class ReportServiceImpl implements ReportService {

    @Autowired
    private CommonAPI commonAPI;
    @Autowired
    private ReportMapper reportMapper;
    @Override
    public Map<String, Object> getMachineReport(Map<String, Object> params) {
        //根据查询参数获取统计
        List<MachineReportVO> list  =reportMapper.getMachineReport(params);
        List<String> ops = new ArrayList<>();
        List<Double> mtbf = new ArrayList<>();
        List<Double> mttf = new ArrayList<>();
        List<Double> mttr = new ArrayList<>();
        Map<String, Object> hashMap = new HashMap<>();
        //根据统计分别计算对应指标
        list.forEach(item->{
            Double t1 = item.getT1();
            Double t2 = item.getT2();
            Double t3 = item.getT3();
            Double n = item.getN();
            item.setMtbf(t1/n);
            item.setMttf(t2/n);
            item.setMttr(t3/n);
            ops.add(item.getOp());
            mtbf.add(item.getMtbf());
            mttf.add(item.getMttf());
            mttr.add(item.getMttr());
        });
        hashMap.put("ops",ops);
        hashMap.put("mtbf",mtbf);
        hashMap.put("mttf",mttf);
        hashMap.put("mttr",mttr);
        return hashMap;
    }

    @Override
    public Map<String, Object> getFTQReport(Map<String, Object> params) {
        //根据日期生成List
        List<LocalDate> dates = generateDatesBetween(LocalDate.parse(params.get("sTime").toString()), LocalDate.parse(params.get("eTime").toString()));
        List<ColumnVO> columnVOS = new ArrayList<>();
        ColumnVO column1 = new ColumnVO("工序编码","center","op");
        column1.setFixed("left");
        columnVOS.add(column1);
        ColumnVO column2 = new ColumnVO("类目","center","metric");
        column2.setFixed("left");
        columnVOS.add(column2);
        dates.forEach(item->{
            String s = formatDate(item);
            ColumnVO column = new ColumnVO(s,"center",s);
            columnVOS.add(column);
        });
        ColumnVO column3 = new ColumnVO("Total","center","total");
        column3.setFixed("right");
        columnVOS.add(column3);
        //解析字符串为LocalDate对象
        Map<String, Object> map = new HashMap<>();
        if (params.containsKey("op")){
            String[] ops = params.get("op").toString().split(",");
            List<String> list = Arrays.asList(ops);
            params.put("opList",list);
        }
        if (params.containsKey("partno")){
            String[] ops = params.get("partno").toString().split(",");
            List<String> list = Arrays.asList(ops);
            params.put("partnoList",list);
        }
        List<FTQReportVO> ftqReport = reportMapper.getFTQReport(params);
        List<Map<String, Object>> list = ReportUtils.convertToColumnFormat(ftqReport);
        //求投入数每日列表
        List<FTQReportVO> qtyList =reportMapper.getQtyList(params);
        Map<String, Object> qtyMap = new HashMap<>();
        Map<String, Object> okMap = new HashMap<>();
        Map<String, Object> scrapMap = new HashMap<>();
        Map<String, Object> ftqMap = new HashMap<>();
        Map<String, Object> obsolescenceMap = new HashMap<>();
        Double qtyTotal = 0.0;
        for (FTQReportVO item : qtyList) {
            qtyTotal+=item.getQty();
            qtyMap.put(item.getDate(), item.getQty());
        }
//        //求产出数每日列表
        Double okTotal = 0.0;
        List<FTQReportVO>  okList =reportMapper.getOkList(params);
        for (FTQReportVO item : okList) {
            okTotal+=item.getQty();
            okMap.put(item.getDate(), item.getQty());
        }
//        //求报废数每日列表
        Double scrapTotal = 0.0;
        List<FTQReportVO>  scrapList =reportMapper.getScrapList(params);
        for (FTQReportVO item : scrapList) {
            scrapTotal+=item.getQty();
            scrapMap.put(item.getDate(), item.getQty());
        }
        qtyMap.forEach((k, v) -> {
            Double v1 = Double.parseDouble(v.toString());
            if (okMap.containsKey(k)){
                Double i = Double.parseDouble(okMap.get(k).toString());
                BigDecimal ftq = BigDecimal.valueOf(i / v1 *100).setScale(2, RoundingMode.HALF_UP);
                if (ftq.doubleValue()>100){
                    ftqMap.put(k,"100%");
                }else {
                    ftqMap.put(k,ftq+"%");
                }
            }else{
                ftqMap.put(k,1);
            }
            if (scrapMap.containsKey(k)){
                Double i = Double.parseDouble(scrapMap.get(k).toString());
                BigDecimal obsolescence = BigDecimal.valueOf(i / v1 *100).setScale(2, RoundingMode.HALF_UP);
                obsolescenceMap.put(k,obsolescence+"%");
            }else{
                obsolescenceMap.put(k,"0%");
            }
        });
        qtyMap.put("metric","投入数");
        qtyMap.put("total",qtyTotal);
        okMap.put("metric","产出良品");
        okMap.put("total",okTotal);
        scrapMap.put("metric","报废数");
        scrapMap.put("total",scrapTotal);
        ftqMap.put("metric","FTQ");
        BigDecimal ftqTotal = BigDecimal.valueOf(okTotal / qtyTotal *100).setScale(2, RoundingMode.HALF_UP);
        ftqMap.put("total",ftqTotal+"%");
        obsolescenceMap.put("metric","报废率");
        BigDecimal obsolescenceTotal = BigDecimal.valueOf(scrapTotal / qtyTotal *100).setScale(2, RoundingMode.HALF_UP);
        obsolescenceMap.put("total",obsolescenceTotal+"%");
        list.add(qtyMap);
        list.add(okMap);
        list.add(scrapMap);
        list.add(ftqMap);
        list.add(obsolescenceMap);
        map.put("report",list);
        map.put("column",columnVOS);
        return map;
    }

    @Override
public ModelAndView exportFtqXls(HttpServletRequest request, HttpServletResponse response, Map<String, Object> param) {
    // 定义easyExcel导出的对象
    ExcelWriter excelWriter = null;
    WriteCellStyle exportExcelStyle = commonAPI.getExportExcelStyle();
    // 头策略使用默认 设置字体大小
    WriteCellStyle headWriteCellStyle = new WriteCellStyle();
    WriteFont headWriteFont = new WriteFont();
    headWriteFont.setFontHeightInPoints((short) 10);
    headWriteCellStyle.setWriteFont(headWriteFont);

    try {
        excelWriter = EasyExcel.write(response.getOutputStream()).build();
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("utf-8");
        String fileName = "FTQ_Report.xlsx";
        response.setHeader("Content-disposition", "attachment;filename=" + fileName);

        ExcelWriterSheetBuilder ftqSheet = EasyExcel.writerSheet(0, "FTQ报表统计");
        ftqSheet.registerWriteHandler(new HorizontalCellStyleStrategy(headWriteCellStyle, exportExcelStyle));

        // 获取报表数据
        Map<String, Object> reportData = getFTQReport(param);
        List<Map<String, Object>> reportList = (List<Map<String, Object>>) reportData.get("report");
        List<ColumnVO> columnList = (List<ColumnVO>) reportData.get("column");

        // 创建动态表头
        List<List<String>> head = new ArrayList<>();
        for (ColumnVO column : columnList) {
            List<String> headCell = new ArrayList<>();
            headCell.add(column.getTitle());
            head.add(headCell);
        }

        // 转换数据格式
        List<Map<Integer, Object>> exportData = new ArrayList<>();
        for (Map<String, Object> rowData : reportList) {
            Map<Integer, Object> exportRow = new LinkedHashMap<>();
            for (int i = 0; i < columnList.size(); i++) {
                ColumnVO column = columnList.get(i);
                Object value = rowData.get(column.getDataIndex());
                exportRow.put(i, value != null ? value.toString() : "");
            }
            exportData.add(exportRow);
        }

        ftqSheet.head(head);
        excelWriter.write(exportData, ftqSheet.build());

    } catch (IOException e) {
        throw new RuntimeException(e);
    } finally {
        if (excelWriter != null) {
            excelWriter.finish();
        }
    }
    return null;
}
    public static List<LocalDate> generateDatesBetween(LocalDate startDate, LocalDate endDate) {
        List<LocalDate> dates = new ArrayList<>();
        LocalDate currentDate = startDate;
        while (!currentDate.isAfter(endDate)) {
            dates.add(currentDate);
            currentDate = currentDate.plusDays(1);
        }

        return dates;
    }

    public String formatDate(LocalDate date) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        return date.format(formatter);
    }
}
